package ua.com.softway.mail;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;

import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;

import ua.com.softway.date.DateTime;
import ua.com.softway.db.date.DateTimeType;
import ua.com.softway.db.date.DateType;

/**
 * Message, that can be serialized
 */
@Entity
@Table(name="generated_message")
@TypeDefs({
   @TypeDef(name="swDate", typeClass=DateType.class),
   @TypeDef(name="swDateTime", typeClass=DateTimeType.class)
})
public class GeneratedMessage {
    @Id @GeneratedValue(strategy=GenerationType.TABLE)
    public int id;
    
    public String replyTo;
    public String subject;
    
    @Lob
    @Column(columnDefinition="mediumtext")
    public String body;
    
    @Column(name="tto")
    public String to;
    
    @Type(type="swDateTime")
    public DateTime generated;
    
    @Type(type="swDateTime")
    public DateTime sent;
    
    public int priority;
    
    public final static String NewMessage = "NewMessage";
    public final static String NoMailAccount = "NoAccount";
    public final static String Sent = "Sent";
    public final static String Error = "Error";
    
    public String state;
    public String cc;
    
    public GeneratedMessage() {
    }
    
    public GeneratedMessage(String replyTo, String subject, String body, String to) {
        this(replyTo, subject, body, to, 0);
    }
    
    public GeneratedMessage(String replyTo, String subject, String body, String to, int priority) {
        this.replyTo = replyTo;
        this.subject = subject;
        this.body = body;
        this.to = to;
        this.priority = priority;
        
        this.generated = DateTime.now();
        this.state = NewMessage;
    }

    private Address address(String emailAddress) throws AddressException {
        String email = "";
        String personal = "";

        int ltIndex = emailAddress.indexOf('<');
        if ( ltIndex == -1 )
            email = emailAddress;
        else {
            int gtIndex = emailAddress.lastIndexOf('>');
            if ( gtIndex == -1 ) throw new AddressException("invalid email address " + emailAddress);

            personal = emailAddress.substring(0, ltIndex);
            email = emailAddress.substring(ltIndex + 1, gtIndex);
        }

        try {
            return new InternetAddress(email, personal, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
    
    private Address[] addresses(String s) throws AddressException {
        String[] ss = s.split(",");
        
        Address[] r = new Address[ss.length];

        for (int i = 0; i < ss.length; i ++)
            r[i] = address(ss[i]);
        
        return r;
    }

    public MimeMessage createMimeMessage(MailAccount mailAccount, Session session) throws MessagingException {
        MimeMessage message = new MimeMessage(session);

        List<Address> recipients = new ArrayList<Address>();
        recipients.add(address(to));

        message.setRecipients(MimeMessage.RecipientType.TO, recipients.toArray(new Address[0]));
        message.setFrom(address(mailAccount.from));
        
        if (this.replyTo != null)
            message.setReplyTo(new Address[] { address(this.replyTo) });
        
        if (this.cc != null)
            message.setRecipients(MimeMessage.RecipientType.CC, addresses(this.cc));

        message.setSubject(subject, "UTF-8");
        
        Multipart content = new MimeMultipart("alternative");
        
        BodyPart textPart = new MimeBodyPart();
        textPart.setContent(stripHtml(body), "text/plain; charset=utf-8");
        
        content.addBodyPart(textPart);
        
        BodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(addHtmlIfRequired(body), "text/html; charset=utf-8");
        
        content.addBodyPart(htmlPart);
        
        message.setContent(content);

        return message;
    }

    private String addHtmlIfRequired(String s) {
        if (s.indexOf("<html>") == -1)
            return "<html>" + s + "</html>";
        
        return s;
    }

    private String stripHtml(String s) {
        return s.replaceAll("\\<.*?>","");
    }
}
